package com.bplow.deep.authority;

import java.util.List;
import java.util.Set;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.AntPathMatcher;
import org.apache.shiro.util.PatternMatcher;
import org.apache.shiro.web.filter.AccessControlFilter;
import org.apache.shiro.web.util.WebUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

public class ShiroDbPermFilter extends AccessControlFilter{

	private final Logger logger = LoggerFactory.getLogger(ShiroDbPermFilter.class);

	private static final String UNAUTHORIZED_URL = "/unauthorized";

	private static final String ROOT_URL = "/";

	@Autowired
	private ShiroAuthService shiroAuthService;

	private List<String> excludeUrls;// 不需要权限验证的URL

	private PatternMatcher pathMatcher = new AntPathMatcher();
	
	@Override
	protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue)
			throws Exception {
		String path = getPathWithinApplication(request);
		if (UNAUTHORIZED_URL.equals(path) || ROOT_URL.equals(path)) {
			return true;
		}
		if (excludeUrls != null && excludeUrls.isEmpty() == false) {
			for (String excludeUrl : excludeUrls) {
				if (pathMatcher.matches(excludeUrl, path))
					return true;
			}
		}
		Subject subject = getSubject(request, response);
		if (subject.getPrincipal() != null) {
			ShiroUser shiroUser = (ShiroUser) subject.getPrincipal();
			if (shiroUser.getId() == 1) {
				return true;
			}
		}
		Set<String> perms = shiroAuthService.getPermsByUrl(path);
		try {
			for (String perm : perms) {
				if (subject.isPermitted(perm))
					return true;
			}
		} catch (Exception e) {
			logger.warn(
					"Make sure permission strings are properly formatted, path: {}",
					path);
			return false;
		}
		return false;
	}

	@Override
	protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
		Subject subject = getSubject(request, response);
		if (subject.getPrincipal() == null) {
			saveRequestAndRedirectToLogin(request, response);
		} else {
			WebUtils.issueRedirect(request, response, UNAUTHORIZED_URL);
		}
		return false;
	}
	
	public void setExcludeUrls(List<String> excludeUrls) {
		this.excludeUrls = excludeUrls;
	}

}
